#include "filelock.h"
#include <stdlib.h>
#include <stdio.h>

static struct flock   lock_it;
static struct flock unlock_it;

file_lock_t* file_lock_new(const char* fname, int fmode)
{
	file_lock_t* me = (file_lock_t*)malloc(sizeof(file_lock_t));
	if (!me)
		return 0;

	if (fname && strlen(fname)){
		me->fd = open(fname, O_CREAT|O_RDWR, fmode);
		if (me->fd == -1) {
			free(me);
			return 0;
		}
		me->fname = strdup(fname);
		fchmod(me->fd, fmode);
	}
	else{
		me->fname = strdup("/tmp/flock_XXXXXX");
		me->fd = mkstemp(me->fname);
		if (me->fd == -1) {
			free(me->fname);
			free(me);
			return 0;
		}
		fchmod(me->fd, fmode);
	}
	
	return me;
}

void file_lock_delete(file_lock_t* me)
{
	if (me) {
		//flock(me->fd, LOCK_UN);
		close(me->fd);
		//remove(me->fname);
		free(me->fname);
		free(me);
	}
}

int file_lock_require(file_lock_t* me, int readonly)
{
	if (me){
		int rc;
		lock_it.l_whence = SEEK_SET; /* from current point */
		lock_it.l_start  = 0;        /* -"- */
		lock_it.l_len    = 0;        /* until end of file */
		lock_it.l_type   = readonly ? F_RDLCK : F_WRLCK;  /* set lock type */
		//lock_it.l_type   = F_WRLCK;  /* set lock type */
		lock_it.l_pid    = 0;        /* pid not actually interesting */

		while (   ((rc = fcntl(me->fd, F_SETLKW, &lock_it)) < 0)
				  && (errno == EINTR)                               ) {
			continue;
		}
		/*if (rc != 0){
			if (readonly)
			WRITELOG(ErrLog, "test: lock_read fail-%d %s", errno, strerror(errno));
			else
			WRITELOG(ErrLog, "test: lock_write fail-%d %s", errno, strerror(errno));
		}
		*/
		return rc;
	}
	else{
		errno = EINVAL;
		return -1;
	}
}

int file_lock_release(file_lock_t* me)
{
	if (me){
		int rc = -1;
		unlock_it.l_whence = SEEK_SET; /* from current point */
		unlock_it.l_start  = 0;        /* -"- */
		unlock_it.l_len    = 0;        /* until end of file */
		unlock_it.l_type   = F_UNLCK;  /* unlock */
		unlock_it.l_pid    = 0;        /* pid not actually interesting */


		while (   ((rc = fcntl(me->fd, F_SETLKW, &unlock_it)) < 0)
				  && (errno == EINTR)) {
			continue;
		}
		/*if (rc != 0)
			WRITELOG(ErrLog, "test: lock release fail-%d %s", errno, strerror(errno));
		*/
		return rc;
	}
	else{
		errno = EINVAL;
		return -1;
	}
}

int file_lock_detect(file_lock_t* me, int readonly)
{
	return 0;
}
